﻿using Digitalmes.DataAccess;
using EFCore.BulkExtensions;
using Elsa.Persistence.EntityFramework.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Channels;
using WalkingTec.Mvvm.Core;

namespace Digitalmes.Services.Hosted
{
    /// <summary>
    /// 批量数据处理服务
    /// </summary>
    public class BatchDataService : BackgroundService
    {
        private readonly ILogService _logger;
        private readonly IServiceProvider _serviceProvider;
        private readonly Channel<SensorData> _dataChannel;
        private readonly int _batchSize;
        private readonly TimeSpan _batchTimeout;
        private readonly int _maxQueueSize;

        public BatchDataService(
            ILogService logger,
            IServiceProvider serviceProvider,
            IConfiguration configuration)
        {
            _logger = logger;
            _serviceProvider = serviceProvider;

            // 从配置中获取参数
            _batchSize = 1000;
            _batchTimeout = TimeSpan.FromMilliseconds(10000);
            _maxQueueSize = 10000;
            // 创建有界通道，防止内存无限增长
            _dataChannel = Channel.CreateBounded<SensorData>(new BoundedChannelOptions(_maxQueueSize)
            {
                FullMode = BoundedChannelFullMode.Wait,
                SingleReader = true,
                SingleWriter = false
            });
        }

        /// <summary>
        /// 添加数据到处理队列
        /// </summary>
        public async ValueTask EnqueueDataAsync(SensorData data)
        {
            try
            {
                await _dataChannel.Writer.WriteAsync(data);
            }
            catch (Exception ex)
            {
                _logger.Error( "将数据添加到处理队列时发生错误",ex);
                // 可以根据需要实现重试或备用存储
            }
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.Information("批量数据处理服务已启动");

            var batch = new List<SensorData>(_batchSize);
            var batchTimer = new PeriodicTimer(_batchTimeout);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    // 等待数据或超时
                    var hasData = await _dataChannel.Reader.WaitToReadAsync(stoppingToken);

                    if (hasData)
                    {
                        // 尝试读取数据，直到达到批次大小或超时
                        while (batch.Count < _batchSize &&
                               _dataChannel.Reader.TryRead(out var data))
                        {
                            batch.Add(data);
                        }

                        // 如果批次已满或超时，处理批次
                        if (batch.Count >= _batchSize ||
                            (batch.Count > 0 && await batchTimer.WaitForNextTickAsync(stoppingToken)))
                        {
                            await ProcessBatchAsync(batch, stoppingToken);
                            batch.Clear();
                            batchTimer = new PeriodicTimer(_batchTimeout); // 重置计时器
                        }
                    }
                }
                catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
                {
                    // 服务正在停止
                    break;
                }
                catch (Exception ex)
                {
                    _logger.Error("处理数据批次时发生错误", ex);
                    await Task.Delay(1000, stoppingToken); // 错误后暂停一下
                }
            }

            // 处理剩余的数据
            if (batch.Count > 0)
            {
                await ProcessBatchAsync(batch, CancellationToken.None);
            }

            _logger.Information("批量数据处理服务已停止");
        }

        /// <summary>
        /// 处理数据批次
        /// </summary>
        private async Task ProcessBatchAsync(List<SensorData> batch, CancellationToken cancellationToken)
        {
            if (batch.Count ==0) return;

            using var scope = _serviceProvider.CreateScope();
            var dbContext = scope.ServiceProvider.GetRequiredService<WTMContext>();

            try
            {
                _logger.Information($"正在处理批次: {batch.Count()} 条记录");

                //使用EF Core的批量添加


                // 使用批量保存（WTM框架扩展）
                await dbContext.DC.BulkInsertAsync(batch);

                _logger.Debug($"成功保存 {batch.Count} 条记录");
            }
            catch (Exception ex)
            {
                _logger.Error($"处理批次时发生错误，批次大小: {batch.Count}",ex);

                // 实现重试逻辑或备用存储
                await HandleFailedBatchAsync(batch, ex);
            }
        }

        /// <summary>
        /// 处理失败的批次
        /// </summary>
        private async Task HandleFailedBatchAsync(List<SensorData> batch, Exception exception)
        {
            // 实现重试逻辑或将数据保存到备用存储（如文件、Redis等）
            // 这里简单记录错误并丢弃数据，实际应用中应该更健壮

            _logger.Error($"批次处理失败，丢弃 {batch.Count} 条记录");

            // 实际实现中可以:
            // 1. 将失败批次保存到文件或Redis
            // 2. 实现指数退避重试
            // 3. 发送警报
        }

        /// <summary>
        /// 获取队列状态
        /// </summary>
        public (int QueueCount, int BatchSize, int MaxQueueSize) GetQueueStatus()
        {
            return (_dataChannel.Reader.Count, _batchSize, _maxQueueSize);
        }
    }
}
